home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
arcers
/
tar316.zip
/
DISK.C
< prev
next >
Wrap
Text File
|
1980-07-24
|
9KB
|
315 lines
/* disk.c - MS-DOS diskette service for Tar program (see file tar.c)
* Author: T.V.Shaporev
* Prepared for release 19 Oct 1990
*
* Called by readtape(), writetape() etc. - see file tape.c
*/
#include "sysup.h"
#ifdef __TURBOC__
#include <string.h>
#include <stdio.h>
#include "modern.h"
#include "define.h"
extern int diskserv __ARGS__((int, int, int, int, int, int, void far *));
extern void printbs __ARGS__(( int ));
static void errdisk __ARGS__(( int ));
static void redrive __ARGS__(( void ));
static int trydisk __ARGS__(( int, char *, int ));
static void nextdisk __ARGS__(( void ));
static void skipsect __ARGS__(( void ));
static void ibmdisk __ARGS__(( int, char *, int ));
static void rainbow __ARGS__(( int, char *, int ));
#define FDC_STATUS (*(char far *)0x0490L)
static unsigned short heads, tracks, sectors, last_seg, this_seg;
static char calibr = 0;
struct { char *type_disk; unsigned size, heads, tracks, sectors; }
ftab[] = { {"fd048ss8", 160, 1, 40, 8 },
{"fd048ss9", 180, 1, 40, 9 },
{"fd048ds8", 320, 2, 40, 8 },
{"fd048ds9", 360, 2, 40, 9 },
{"fd135ds9", 720, 2, 80, 9 },
{"fd096ds9", 720, 2, 80, 9 },
{"fd096ds15", 1200, 2, 80, 15 },
{"fd135ds18", 1440, 2, 80, 18 } };
static void errdisk(n)
int n;
{
register int i;
static struct { unsigned char code; char *text; } errtab[] = {
{ 0, "undefined error" },
{ 0x00, "no error on last operation" },
{ 0x01, "invalid request to controller" },
{ 0x02, "bad address mark" },
{ 0x03, "write protect" },
{ 0x04, "sector ID bad or not found" },
{ 0x05, "reset failed" },
{ 0x06, "floppy changed line on" },
{ 0x08, "DMA failure" },
{ 0x09, "DMA overrun: attempted to write across 64K" },
{ 0x0b, "bad track flag encountered" },
{ 0x0C, "media type not found" },
{ 0x10, "bad CRC: invalid CRC when data checked" },
{ 0x11, "recoverable error found; data corrected" },
{ 0x20, "controller failure" },
{ 0x40, "bad seek; requested track not found" },
{ 0x80, "time out; drive did not respond" },
{ 0xff, "sense operation failed" } };
for (i=1; errtab[i].code!=n && i<dimof(errtab); i++) ;
if (i>=dimof(errtab)) i = 0;
fprintf(myout, "Tar: diskette error: %s\n", errtab[i].text);
}
int argdisk(k)
register k;
{
register i;
for (i=0; ftab[i].size!=k && i<dimof(ftab); i++) ;
if (i >= dimof(ftab)) return -1;
sectors = ftab[i].sectors;
tracks = ftab[i].tracks;
heads = ftab[i].heads;
return 0;
}
int defdev(k)
register char *k;
{
register i;
for (i=0; stricmp(ftab[i].type_disk, k)!=0 && i<dimof(ftab); i++) ;
if (i < dimof(ftab)) {
sectors = ftab[i].sectors;
tracks = ftab[i].tracks;
heads = ftab[i].heads;
} else if (stricmp("rainbow", k) == 0) {
calibr = RAINBOW;
sectors = 10;
tracks = 80;
heads = 1;
} else {
return -1;
}
return 0;
}
static void redrive() /* reset & recalibrate drive */
{
(void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
if (calibr & QUADISK) {/* Init 800 */
FDC_STATUS = 0x61; /* FDC status buts <- 61h - ??? */
/* verify Track 0 Sector 1 Side 0 */
(void)diskserv(4, ndrive, 0, 0, 1, 1, NULL);
/* verify Track 1 Sector 1 Side 0 */
(void)diskserv(4, ndrive, 0, 1, 1, 1, NULL);
(void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
FDC_STATUS = 0x54; /* FDC status buts <- 54h - ??? */
} else if (calibr != 0) {
(void)diskserv(0x17, ndrive, 0, 0, 1, calibr, NULL);
}
}
void inidisk(void)
{
register k;
unsigned tb;
struct {
short int ndisks, maxhead, maxtrack, maxsect;
} dp;
if (!calibr) {
/* reset drive */
(void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
/* get drive params (set default to 2x40x9) */
(void)diskserv(8, ndrive, 1, 39, 9, 9, &dp);
if ((tb = ++(dp.maxhead) * ++(dp.maxtrack) * dp.maxsect) == 0) {
fprintf(stderr, "Tar: drive not present\n");
done(ERINIT);
}
if (!k_flag) {
sectors = dp.maxsect; tracks = dp.maxtrack; heads = dp.maxhead;
if (v_flag) fprintf(myout, "Diskette capacity %uK assigned\n",
tb / (1024/BLKSIZE) );
}
last_seg = sectors*tracks*heads;
if (last_seg == 2880) {
calibr = tb == 2880 ? 3 : 0;
} else if (last_seg == 2400) {
calibr = tb == 2400 ? 3 : 0;
} else if (last_seg == 1440) {
calibr = tb == 2880 ? 2 :
tb == 2400 ? QUADISK :
tb == 1440 ? 4 : 0;
} else if (last_seg == 720) {
calibr = tb == 2400 ? 2 : tb == 720 ? 1 : 0;
} else if (last_seg == 640) {
calibr = tb == 2400 ? 2 : tb == 720 || tb == 640 ? 1 : 0;
} else if (last_seg == 360) {
calibr = tb == 2400 ? 2 : tb == 720 || tb == 360 ? 1 : 0;
} else if (last_seg == 320) {
calibr = tb == 2400 ? 2 : tb == 720 || tb == 360 ||
tb == 640 || tb == 320 ? 1 : 0;
}
}
this_seg = 0;
redrive();
/* get drive error status */
k = diskserv(1, ndrive, 0, 0, 1, 1, NULL);
if (k!=0 && k!=6) {
errdisk(k);
if (k!=0x11) done(ERINIT);
}
if (!cblock) {
/* Some BIOSes do strange things on quad drives. */
/* I guess they loose info while read or write through 9th to */
/* 10th sector. I hope, the following solves the problem. */
printbs(cblock = a_flag ? 1 : (sectors < 9 ? sectors : 3));
}
}
static int trydisk(wr, buf, bl)
int wr, bl;
char *buf;
{
int i, k;
register short s, h, t;
s = this_seg % sectors + 1; /* sector */
t = this_seg / sectors;
h = t % heads; /* head */
t /= heads; /* track */
i = 0;
do {
k = diskserv((wr ? 3 : 2), ndrive, h, t, s, bl, buf);
#if 0
if (!k && wr) {/* verify */
char chk[NBLOCK*BLKSIZE];
k = diskserv(4, ndrive, h, t, s, bl, buf);
}
#endif
if (k) redrive();
} while (k && ++i<3);
if (cbreak) done(0);
if (k == 0 || k == 0x11) {
k = 0;
} else if (k!=0x02 && k!=0x04 && k!=0x0B && k!=0x10 && k!=0x40) {
errdisk(k); /* fatal error */
if (!i_flag || wr) done(wr ? EWRITE : ERREAD);
}
return k;
}
static void nextdisk()
{
fprintf(stderr, "Tar: insert NEXT diskette and press ENTER when ready...");
(void)yes_no('\0');
this_seg = 0;
redrive();
}
static void skipsect()
{
fprintf(myout, "Tar: warning: bad sector %d, skipped\n", this_seg);
}
static void ibmdisk(wr, buf, bl)
int wr, bl;
char *buf;
{
int i, j, k;
i = sectors - this_seg % sectors;
if (i > bl) i = bl;
while (bl > 0) {
if (this_seg >= last_seg) nextdisk();
if ((k = trydisk(wr, buf, i)) == 0) {
this_seg += i;
buf += i*BLKSIZE;
bl -= i;
} else {
for (j=0; j<i; j++) {
if (i>1) k = trydisk(wr, buf, 1);
if (k == 0) { /* one sector o'k */
buf += BLKSIZE;
--bl;
} else skipsect();
++this_seg;
}
}
i = sectors < bl ? sectors : bl;
}
}
static void rainbow(wr, buf, bl)
int wr, bl;
char *buf;
{
int i, j, k, n;
static char e85tab[50] = {
/* x = 0 1 2 3 4 5 6 7 8 9 */
/* 0x */ 1, 3, 5, 7, 9, 2, 4, 6, 8, 10,
/* 1x */ 3, 5, 7, 9, 1, 4, 6, 8, 10, 2,
/* 2x */ 5, 7, 9, 1, 3, 6, 8, 10, 2, 4,
/* 3x */ 7, 9, 1, 3, 5, 8, 10, 2, 4, 6,
/* 4x */ 9, 1, 3, 5, 7, 10, 2, 4, 6, 8,
};
while (bl > 0) {
if (this_seg >= last_seg) nextdisk();
i = (this_seg/10 + 1) % 80; /* track */
j = e85tab[this_seg%50]; /* sector */
n = 0;
do {
k = diskserv((wr?3:2), ndrive, 0, i, j, 1, buf);
if (k && ++n<3) redrive();
} while (k && n<3);
if (cbreak) done(0); /* ??? */
if (!k) { buf += BLKSIZE; --bl; } else skipsect();
++this_seg;
}
}
/* Interface routines */
int dread(buf, n)
char *buf; register n;
{
register k = n / BLKSIZE;
if (n % BLKSIZE) return -1;
if (calibr == RAINBOW) rainbow(0, buf, k); else ibmdisk(0, buf, k);
return n;
}
int dwrite(buf, n)
char *buf; register n;
{
n = (BLKSIZE-1 + n) / BLKSIZE;
if (calibr == RAINBOW) rainbow(1, buf, n); else ibmdisk(1, buf, n);
return BLKSIZE*n;
}
int dback(n)
register n;
{
this_seg = this_seg > n ? this_seg-n : 0;
return n;
}
#endif